package com.glsc.ngateway.filetransfer.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import com.glsc.ngateway.common.api.common.enums.DictConstant;
import com.glsc.ngateway.common.api.common.utils.CommonUtils;
import com.glsc.ngateway.common.api.filetransfer.dto.CommonFileDto;
import com.glsc.ngateway.common.api.filetransfer.enums.CommonTypeEnum;
import com.glsc.ngateway.common.base.domain.mysql.fileTransfer.CommonFile;
import com.glsc.ngateway.common.base.repo.mysql.filetransfer.CommFileRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Slf4j
@Service
public class CommonFileService {
    private List<String> allowFileTypeList = new ArrayList<>(Arrays.asList("jpg", "jpeg", "gif", "png", "pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx"));

    @Value("${commonFile.nas.path.commonfile}")
    String documentNasPath = "";

    @Resource
    private CommFileRepository commFileRepository;

    /**
     * 保存
     *
     * @param commonFile
     * @return
     */
    public CommonFile save(CommonFile commonFile) {
        if (Objects.isNull(commonFile)) {
            return null;
        }
        return commFileRepository.save(commonFile);
    }

    /**
     * 条件查询
     *
     * @param commonFile
     * @return
     */
    public List<CommonFile> findByCondition(CommonFile commonFile) {
        if (Objects.isNull(commonFile)) {
            return null;
        }
        List<CommonFile> fileList = commFileRepository.findAll(Example.of(commonFile));
        return fileList;
    }

    /**
     * 根据id查找
     *
     * @param id
     * @return
     */
    public CommonFile findById(Integer id) {
        Optional<CommonFile> optional = commFileRepository.findById(id);
        if (optional.isPresent()) {
            return optional.get();
        }
        return null;
    }

    /**
     * 根据fileId查询
     *
     * @param fileId
     * @return
     */
    public CommonFile findByFileId(String fileId, String systemCode) {
        CommonFile condition = CommonFile.builder().deleted(DictConstant.NO).fileStatus(DictConstant.YES)
                .fileSource(systemCode).fileId(fileId).build();
        if (StringUtils.isNotBlank(systemCode)) {
            condition.setFileSource(systemCode);
        }

        List<CommonFile> commonFiles = findByCondition(condition);

        if (CollectionUtil.isNotEmpty(commonFiles)) {
            return commonFiles.get(0);
        }
        return null;
    }

    /**
     * @param file       文件
     * @param systemCode 系统编码
     * @param fileId     文件id-更新时使用
     * @return
     * @throws IOException
     */
    @Transactional
    public CommonFileDto uploadFile(MultipartFile file, String systemCode, String fileId, String oaAccount, String creatorName, String fileDesc) throws IOException {

        String oFileName = file.getOriginalFilename();
        log.info("上传的文件名：" + oFileName);

        Assert.isTrue(Objects.nonNull(CommonTypeEnum.findByCode(systemCode)), "查询文件的systemCode错误");

        Assert.isTrue((StringUtils.isNotBlank(oFileName) && oFileName.length() > 4), "上传文件名不合法，文件名至少4个字符");
        CommonFile oldCommonFile = null;
        if (StringUtils.isNotBlank(fileId)) {
            oldCommonFile = findByFileId(fileId, systemCode);
            Assert.isTrue(Objects.nonNull(oldCommonFile), "未查询到fileId=" + fileId + "的文件信息，更新失败");
            oldCommonFile.setFileStatus(DictConstant.NO);
            commFileRepository.save(oldCommonFile);
        }

        oFileName = CommonUtils.getFileNameFromPath(oFileName);//去除可能的文件路径（解决IE下带路径问题）

        int lastPos = oFileName.lastIndexOf(".");//lastPos=-1,没有文件类型后缀

        String fileSuffix = null;
        if (lastPos > 0 && lastPos < oFileName.length()) {
            fileSuffix = oFileName.substring(lastPos + 1).toLowerCase();
        }
        if (StrUtil.isEmpty(fileSuffix)) {
            fileSuffix = "";
        }
        fileSuffix = fileSuffix.toLowerCase();
        log.info("上传文件类型" + fileSuffix + "，文件全称：" + oFileName);

        Assert.isTrue(allowFileTypeList.contains(fileSuffix), "只能上传jpg/jpeg/gif/png/pdf/doc/xls/ppt类型的文件");
        Assert.isTrue(file.getSize() < 1024 * 1000 * 100, "档案不得大于100M，实际上传文件大小为" + file.getSize() / (1000.0 * 1024));

        String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        String uuid = null;

        if (StringUtils.isNotBlank(fileId)) {
            uuid = oldCommonFile.getFileId();
        } else {
            uuid = UUID.randomUUID().toString().replaceAll("-", "");
        }

        String path = documentNasPath + systemCode + "/" + time + "/" + uuid + "/" + oFileName;


        File destFile = new File(path);
        try {
            log.info("存储文件至目录" + destFile.getAbsolutePath());
            FileUtils.copyInputStreamToFile(file.getInputStream(), destFile);
        } catch (IOException e) {
            String errMsg = "上传产品档案失败，原因：" + e.getLocalizedMessage();
            log.error(errMsg, e);
            Assert.isTrue(false, "上传文件失败，原因：" + e.getLocalizedMessage());
        }

        Digester digester = new Digester(DigestAlgorithm.MD5);
        String md5Value = digester.digestHex(destFile);

        CommonFile commonFile = new CommonFile();
        commonFile.setFileName(oFileName);
        commonFile.setFileMd5(md5Value);
        commonFile.setFilePath(path);
        commonFile.setCreateOperator(oaAccount);
        commonFile.setCreateOperatorName(creatorName);
        commonFile.setFileSize(file.getSize());
        commonFile.setFileSource(systemCode);
        commonFile.setFileStatus(DictConstant.YES);
        commonFile.setFileId(uuid);
        commonFile.setDeleted(DictConstant.NO);
        commonFile.setCreateTime(LocalDateTime.now());
        commonFile.setFileDesc(fileDesc);
        CommonFile resCommonFile = commFileRepository.save(commonFile);

        CommonFileDto commonFileDto = new CommonFileDto();
        BeanUtils.copyProperties(resCommonFile, commonFileDto);
        return commonFileDto;
    }

}
